﻿Imports System.Text
Imports System.Collections.Generic
Imports System.Web

Public Class Document
	Private Const SpacesPerTab As Integer = 4
	Private Const _SampleCSS As String = ""

	Dim _FullDocument As String
	Dim _DocumentBlocks As List(Of DocumentBlock)

	Dim _HTMLTableClass As String
	Dim _HTMLCodeCellClass As String
	Dim _HTMLCommentCellClass As String
	Dim _HTMLRowClass As String
	Dim _HTMLTable As String
	Dim _HTMLCaptionClass As String
	Dim _HTMLHeaderClass As String
	Dim _HTMLCodeClass As String

	Public Property FullDocument() As String
		Get
			Return _FullDocument
		End Get
		Set(ByVal value As String)
			_FullDocument = value
		End Set
	End Property
	Public ReadOnly Property DocumentBlocks() As List(Of DocumentBlock)
		Get
			Return _DocumentBlocks
		End Get
	End Property
	Public Property HTMLCodeCellClass() As String
		Get
			Return _HTMLCodeCellClass
		End Get
		Set(ByVal value As String)
			_HTMLCodeCellClass = value
		End Set
	End Property
	Public Property HTMLCommentCellClass() As String
		Get
			Return _HTMLCommentCellClass
		End Get
		Set(ByVal value As String)
			_HTMLCommentCellClass = value
		End Set
	End Property
	Public Property HTMLRowClass() As String
		Get
			Return _HTMLRowClass
		End Get
		Set(ByVal value As String)
			_HTMLRowClass = value
		End Set
	End Property
	Public Property HTMLTableClass() As String
		Get
			Return _HTMLTableClass
		End Get
		Set(ByVal value As String)
			_HTMLTableClass = value
		End Set
	End Property
	Public Property HTMLCaptionClass() As String
		Get
			Return _HTMLCaptionClass
		End Get
		Set(ByVal value As String)
			_HTMLCaptionClass = value
		End Set
	End Property
	Public Property HTMLHeaderClass() As String
		Get
			Return _HTMLHeaderClass
		End Get
		Set(ByVal value As String)
			_HTMLHeaderClass = value
		End Set
	End Property
	Public Property HTMLCodeClass() As String
		Get
			Return _HTMLCodeClass
		End Get
		Set(ByVal value As String)
			_HTMLCodeClass = value
		End Set
	End Property
	Public ReadOnly Property HTMLTable()
		Get
			Return _HTMLTable
		End Get
	End Property
	Public ReadOnly Property SampleCSS() As String
		Get
			Return _SampleCSS
		End Get
	End Property

	Sub New(ByVal Source As String)
		_FullDocument = Source
		Call CutDocument()
	End Sub
	''' <summary>
	''' Cuts the document into Comments and Codes blocks
	''' </summary>
	''' <remarks></remarks>
	Private Sub CutDocument()
		Dim DocumentRows As String()
		Dim CodeRows As StringBuilder
		Dim CommentRows As StringBuilder
		Dim CurrBlock As DocumentBlock
		Dim RunningCode As Boolean
		Dim RunnginComment As Boolean
		Dim RunningCommentBlock As Boolean

		_DocumentBlocks = New List(Of DocumentBlock)
		DocumentRows = FullDocument.Split(Environment.NewLine)

		RunnginComment = False
		RunningCode = False
		RunningCommentBlock = False

		For Each DocumentRow As String In DocumentRows
			Dim PolishDocumentRow As String
			PolishDocumentRow = DocumentRow.Trim

			If PolishDocumentRow <> "" Then	'TODO You are ignoring blank lines, think about it
				Select Case PolishDocumentRow.Substring(0, 1)
					Case "/", "'"
						If RunningCode Then	'there is a running instance of code
							If CommentRows Is Nothing Then
								CommentRows = New StringBuilder
								CommentRows.Append("")
							End If
							If CodeRows Is Nothing Then
								CodeRows = New StringBuilder
								CodeRows.Append("")
							End If
							CurrBlock = New DocumentBlock(CodeRows.ToString, CommentRows.ToString)
							_DocumentBlocks.Add(CurrBlock)
							CodeRows = Nothing
							CommentRows = Nothing
							CurrBlock = Nothing
							RunningCode = False
						End If

						If PolishDocumentRow.Substring(0, 2) = "/*" Then 'C comment block starts
							If PolishDocumentRow.IndexOf("*/") < 0 Then	'The C block is closed on the same row
								RunningCommentBlock = True
							End If
						End If

						If Not RunnginComment Then 'Comment is not going on already
							CommentRows = New StringBuilder
						End If

						If CommentRows Is Nothing Then 'TODO this shouldn't be necessary, try to remove it
							CommentRows = New StringBuilder
						End If
						CommentRows.Append(DocumentRow)
						RunnginComment = True
					Case Else
						If Not RunningCommentBlock Then
							If Not RunningCode Then
								CodeRows = New StringBuilder
								RunningCode = True
								RunnginComment = False
							End If
							If CodeRows Is Nothing Then
								CodeRows = New StringBuilder
							End If
							CodeRows.Append(DocumentRow)
						Else
							CommentRows.Append(DocumentRow)
							If PolishDocumentRow.IndexOf("*/") > -1 Then 'The comment block is closed
								RunningCode = True 'This will cause the comment to be closed on next iteration
								RunningCommentBlock = False
							End If
						End If
				End Select
			End If
		Next
	End Sub
	''' <summary>
	''' Creates an HTML table containing Comments block on the left and related Code blocks on the right
	''' </summary>
	''' <remarks></remarks>
	Public Sub CreateHTMLTable(ByVal WithCaption As Boolean, ByVal WithHeaders As Boolean)
		Dim Table As New StringBuilder

		With Table
			.Append(AddClassToTag("table", _HTMLTableClass))
			.Append(Environment.NewLine)

			If WithCaption Then
				.Append(AddClassToTag("caption", _HTMLCaptionClass))
				.Append(FormatTextHTML("Test caption", False))
				.Append("</caption>")
			End If

			If WithHeaders Then
				.Append(AddClassToTag("th", _HTMLHeaderClass))
				.Append(FormatTextHTML("Comments", False))
				.Append("</th>")

				.Append(AddClassToTag("th", _HTMLHeaderClass))
				.Append(FormatTextHTML("Code", False))
				.Append("</th>")
			End If

			For Each codeBlock As DocumentBlock In _DocumentBlocks
				.Append(AddClassToTag("tr", _HTMLRowClass))
				.Append(AddClassToTag("td", _HTMLCommentCellClass))
				.Append(FormatTextHTML(codeBlock.Comment, False))
				.Append("</td>" & AddClassToTag("td", _HTMLCodeCellClass))

				.Append(AddClassToTag("code", _HTMLCodeClass))
				.Append(FormatTextHTML(codeBlock.Code, True))
				.Append("</code>")

				.Append("</td></tr>")
				.Append(Environment.NewLine)
			Next

			Table.Append("</table>")
		End With

		_HTMLTable = Table.ToString
	End Sub
	Private Function FormatTextHTML(ByVal OriginalText As String, ByVal ConvertNbSp As Boolean) As String
		Dim HTMLSafeText As String
		Dim TabBuilder As New StringBuilder

		For i = 0 To SpacesPerTab
			TabBuilder.Append("&nbsp;")
		Next

		HTMLSafeText = HttpUtility.HtmlEncode(OriginalText)
		If ConvertNbSp Then
			HTMLSafeText = HTMLSafeText.Replace(" ", "&nbsp;")
			HTMLSafeText = HTMLSafeText.Replace(System.Convert.ToChar(9), TabBuilder.ToString)
		End If

		HTMLSafeText = HTMLSafeText.Replace(System.Convert.ToChar(10), "<br />")

		Return HTMLSafeText
	End Function
	Private Function AddClassToTag(ByVal Tag As String, ByVal CSSClass As String) As String
		Dim FullTag As String

		If (CSSClass IsNot Nothing) AndAlso (CSSClass.Trim <> "") Then
			FullTag = "<" & Tag & " class=""" & CSSClass & """>"
		Else
			FullTag = "<" & Tag & ">"
		End If

		Return FullTag
	End Function
End Class
Public Class DocumentBlock
	Dim _Code As String
	Dim _Comment As String

	Public Property Code() As String
		Get
			Return _Code
		End Get
		Set(ByVal value As String)
			_Code = value
		End Set
	End Property
	Public Property Comment() As String
		Get
			Return _Comment
		End Get
		Set(ByVal value As String)
			_Comment = value
		End Set
	End Property

	Sub New(ByVal CodeBlock As String, ByVal CommentBlock As String)
		_Code = CodeBlock
		_Comment = CommentBlock
	End Sub
End Class